﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace Utils.Log
{
    public delegate void LogEventHandler(string log);
    /// <summary>
    /// 高效日志工作线程(并不)
    /// </summary>
    public class LogWorker : WorkerBase
    {
        /// <summary>
        /// 日志缓存区
        /// </summary>
        //private static List<string> logs;
        private static BlockingCollection<string> logs;
        //private readonly int max_log_size = 1000;
        private StreamWriter log_file;
        private DateTime last_date;
        private static readonly int max_stack_size = 100000;
        //private Stopwatch sw;

        /// <summary>
        /// 所有日志的事件
        /// </summary>
        public event LogEventHandler OnLog;


        public string Log_folder_path { get; set; }
        public string Log_path { get; private set; }

        public LogWorker(string log_folder_path)
        {
            this.Log_folder_path = log_folder_path;
            logs = new BlockingCollection<string>();
        }

        protected override void Run()
        {
            Init();
            while (loop)
            {
                DateTimeChanged();
                Work();
                System.Threading.Thread.Sleep(100);
            }
            Exit();
        }

        /// <summary>
        /// 初始化
        /// </summary>
        private void Init()
        {
            //sw = new Stopwatch();
            //sw.Start();
            //打开日志文件 日志文件格式 20170101 12-00-00.log
            //log_path = log_folder_path + @"\" + DateTime.Now.ToString("yyyyMMdd HH-mm-ss") + @".log";
            last_date = DateTime.Now;
            Log_path = Log_folder_path + @"\" + last_date.ToString("yyyyMMdd") + @".log";//打开日志文件 日志文件格式 20170101.log
            log_file = new StreamWriter(Log_path, true)
            {
                AutoFlush = true
            };
            Write(System.Windows.Application.Current.FindResource("log_start") as string);
        }

        internal void Write(dynamic s)
        {
            if (!logs.IsCompleted)
                logs.TryAdd(DateTime.Now.ToString("[HH:mm:ss]") + s + Environment.NewLine);
        }
        /// <summary>
        /// 取出日志队列操作
        /// </summary>
        /// <returns>队头的日志</returns>
        private string[] Read()
        {

            if (logs.Count >= 0)
            {
                List<string> t_list = new List<string>(logs.Count);
                while (logs.Count != 0)
                {
                    t_list.Add(logs.Take());
                    if (t_list.Count > max_stack_size)
                        break;
                }
                return t_list.ToArray();
            }
            else
                return new string[] { };
        }

        private void DateTimeChanged()
        {
            var now = DateTime.Now;
            if (last_date.Year != now.Year || last_date.DayOfYear != now.DayOfYear)
            {
                try
                {
                    log_file.Close();
                    Log_path = Log_folder_path + @"\" + now.ToString("yyyyMMdd") + @".log";//打开日志文件 日志文件格式 20170101.log
                    log_file = new StreamWriter(Log_path, true)
                    {
                        AutoFlush = true
                    };
                    Write(System.Windows.Application.Current.FindResource("day_changed") as string);
                    last_date = now;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
        }
        /// <summary>
        /// 工作
        /// </summary>
        private void Work()
        {
            if (logs.Count > 150)
            {
                Task.Run(() =>
                {
                    WriteLog();
                });
            }
            else
            {
                WriteLog();
            }
        }

        /// <summary>
        /// 退出
        /// </summary>
        private void Exit()
        {
            try
            {
                Write(System.Windows.Application.Current.FindResource("log_exit") as string);

                //sw.Stop();
                //Write("耗时" + sw.Elapsed);
                //Write("共" + write_count + "条日志");
                //Write("平均" + (write_count / sw.Elapsed.TotalMilliseconds) + "条日志/毫秒");

                WriteLog();
                log_file.Close();
            }
            catch (EncoderFallbackException e)
            {
                System.Console.WriteLine(e.ToString());
            }
        }

        /// <summary>
        /// 写入文件
        /// </summary>
        private void WriteLog()
        {
            string[] logs = Read();
            //write_count += logs.Length;
            StringBuilder sb = new StringBuilder(512);
            foreach (var s in logs)
            {
                sb.Append(s);
            }
            string t_logs = sb.ToString();
            //logs.ForEach(l => t_logs += l);//效率低
            if (t_logs != String.Empty)
            {
                try
                {
                    log_file.Write(t_logs);
                    OnLog?.Invoke(t_logs);
                }
                catch (ObjectDisposedException e)
                {
                    System.Console.WriteLine(e.ToString());
                }
            }
        }

    }
}
